/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package com.home.logic;

import com.home.common.ApplicationCommon;
import com.home.common.Constants;
import com.home.common.utils.DateUtils;
import com.home.dao.AttributeDao;
import com.home.dao.AttributeGroupDao;
import com.home.dao.ScorecardDao;
import com.home.dao.ScorecardGroupAttributeResultDao;
import com.home.mapping.AttributeGroup;
import com.home.mapping.Scorecard;
import com.home.mapping.ScorecardGroupAttributeResult;
import com.home.mapping.Venture;
import com.home.model.dto.ReportAVGScoreMapWeekDto;
import com.home.model.dto.ReportAverageScoreDto;
import com.home.model.dto.ReportPerOfAttrDto;
import com.home.model.dto.ReportPerOfAttrMapDto;
import com.home.model.dto.ReportPerOfCateDto;
import com.home.model.dto.ReportPerOfCateMapDto;
import com.home.model.dto.ReportTotalEvaluationDto;
import com.home.model.dto.ReportTotalEvaluationMapWeekDto;
import com.home.model.table.AgentRankObjTable;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.poi.ss.formula.functions.Rank;

/**
 *
 * @author pnduy
 */
public class ReportLogic {
    public Map<String, Map<Integer, Double>> getMapDataForTotalScoreOfVentureInWeeks(int weekFrom, int weekTo, List<Venture> ventures, Integer scorecardTypeId) {
        
        List<Integer> weeks = ApplicationCommon.getSerialWeeks(weekFrom, weekTo);
        List<Scorecard> scorecards = new ScorecardLogic().findScForInboundVentureReport(weekFrom, weekTo, scorecardTypeId);
        Map<String, Map<Integer, Double>> mapResult = new HashMap<>();
        Map<Integer, Date[]> mapWeekInYear = DateUtils.getMapWeekInCurrentYear();
        for (Venture venture : ventures) {
            Map<Integer, Double> map = new TreeMap<>();
            for (Integer week : weeks) {
                
                Date dateFrom = mapWeekInYear.get(week)[0];
                Date dateTo = mapWeekInYear.get(week)[1];
                Double total = 0.0;
                int times = 0;
                for (Scorecard sc : scorecards) {
                    if (sc.getAgent().getTeam().getVenture().getIdVenture() == venture.getIdVenture()) {
                        if (sc.getEvalutationDate().after(dateFrom) && sc.getEvalutationDate().before(dateTo)) {
                            if (sc.getTotalScore() != null) {
                                total += sc.getTotalScore();
                            }
                            times++;
                        }
                    }
                }
                Double result = 0.0;
                if (times > 0) {
                    result = total / times;
                } else {
                    result = total;
                }
                map.put(week, result);                
            }
            mapResult.put(venture.getVentureName(), map);
        }
               
        return mapResult;
    }
    
//    public Map<String, Double> getMapDataForGroupAttrScoreReport(List<Venture> ventures, int week, Integer type, List<AttributeGroup> listAttrGroup, Integer scorecardTypeId) {
//        Map<String, Double> mapData = new TreeMap<>();
//
//        Map<Integer, Date[]> mapWeekInYear = DateUtils.getMapWeekInCurrentYear();
//        Date dateFrom = mapWeekInYear.get(week)[0];
//        Date dateTo = mapWeekInYear.get(week)[1];
//        List<Scorecard> scorecards = new ScorecardDao().findScorecardsInPeriod(dateFrom, dateTo, scorecardTypeId);
//        
//        List<Integer> listIdsSc = new ArrayList<>();
//        for (Scorecard sc : scorecards) {
//            listIdsSc.add(sc.getIdScorecard());
//        }
//        DecimalFormat df = new DecimalFormat("#.#");   
//        List<ScorecardGroupAttributeResult> listScorecardGroupAttributeResult = new ScorecardGroupAttributeResultDao().findByScorecardIds(listIdsSc);
//        for (AttributeGroup atrrGroup : listAttrGroup) {
//
//            for (Venture venture : ventures) {
//                Double value = 0.0;
//                int times = 0;
//
//                for (ScorecardGroupAttributeResult scGroupAttrResult : listScorecardGroupAttributeResult) {
//                    if (atrrGroup.getIdAttributeGroup().compareTo(scGroupAttrResult.getAttributeGroup().getIdAttributeGroup()) == 0
//                            && (venture.getIdVenture().compareTo(scGroupAttrResult.getScorecard().getAgent().getTeam().getVenture().getIdVenture()) == 0)) {
//                        value += scGroupAttrResult.getScore();
//                        times++;
//                    }
//
//                }
//                Long result = 0L;
//                if (times > 0) {
//                    result = value / times;
//                } else {
//                    result = value;
//                }
//                // parse result to %
//                double finalResult = (double)result / atrrGroup.getAttributeGroupWeight();
//                Double r = (Double.valueOf(df.format(finalResult)) * 100; 
//                mapData.put(atrrGroup.getAttributeGroupName() + "---" + venture.getVentureName(), r);
//            }
//
//        }
//
//        return mapData;
//    }
    
    public Map<String, Double> getMapDataForGroupAttrScoreReport_Sinh(List<Venture> ventures, int week, Integer type, List<AttributeGroup> listAttrGroup) {
        Map<String, Double> mapData = new TreeMap<>();

        Map<Integer, Date[]> mapWeekInYear = DateUtils.getMapWeekInCurrentYear();
        Date dateFrom = mapWeekInYear.get(week)[0];
        Date dateTo = mapWeekInYear.get(week)[1];
                
        List<Object[]> listTest = new ScorecardDao().getAttributeGroupResult(dateFrom, dateTo, type);
        DecimalFormat df = new DecimalFormat("#.#");
        
        for (Object[] item : listTest){
            int i = 0;
            String legend = "";
            Double r = 0.0;
            for (Object item_1 : item){
                if (i == 0)
                    legend = item_1.toString();
                if (i == 1)
                    legend = item_1.toString() + "---" + legend;
                if (i == 2)
                    r = (Double.valueOf(df.format(item_1)) * 1.0);
                i++;
            }
            mapData.put(legend, r);
        }
        
        return mapData;
    }
    
    public Map<Integer, Double> getDataForAVGScoreReport(int weekFrom, int weekTo, Integer scorecardType, Integer ventureId) {
        Map<Integer, Double> map = new TreeMap<>();
        
        List<Object[]> listData = new ScorecardDao().getAvgScoreOfVentureInWeeks(weekFrom, weekTo, scorecardType, ventureId);
        DecimalFormat df = new DecimalFormat("#.#");
        
        for (Object[] item : listData) {
            Integer itemWeek = Integer.parseInt(item[0].toString());
            Double itemScore = (Double.valueOf(df.format(item[0])) * 1.0);
            map.put(itemWeek, itemScore);
        }
        
        return map;
    }
    
    public List<AgentRankObjTable> getDataForAgentRankReport(int weekFrom, int weekTo, Integer scorecardType, Integer ventureId) {
        List<Object[]> listObj = new ScorecardDao().findRankOfAgentInWeeks(weekFrom, weekTo, scorecardType, ventureId);
        List<AgentRankObjTable> listResult = new ArrayList<>();
        int i = 0;
        DecimalFormat df = new DecimalFormat("##.#");
        for (Object[] obj : listObj) {
            i++;
            AgentRankObjTable agentRankObj = new AgentRankObjTable();
            agentRankObj.setRank(i);
            agentRankObj.setAgentName(obj[0].toString());
            double score = Double.valueOf(df.format(obj[1]));
            agentRankObj.setAvgScore(score);
            
            listResult.add(agentRankObj);
        }
        return listResult;
    }
    
    public List<ReportAverageScoreDto> parseDataReportAverageScore(int typePeriod, int periodFrom, int periodTo, Integer chanelId, int group, List<Integer> groupIdValues, int yearFrom, int yearTo, Integer ventureId) {
        List<Object[]> listObject = null;
        if (typePeriod == Constants.PERIOD_TYPE_WEEKLY) {
            listObject = new ScorecardDao().findAverageScoreReportWeek(periodFrom, periodTo, chanelId, group, groupIdValues, yearFrom, ventureId);
        } else if (typePeriod == Constants.PERIOD_TYPE_MONTHLY){
            listObject = new ScorecardDao().findAverageScoreReportMonth(periodFrom, periodTo, chanelId, group, groupIdValues, yearFrom, yearTo, ventureId);
        } else {
            listObject = new ScorecardDao().findAverageScoreReportQuarter(periodFrom, periodTo, chanelId, group, groupIdValues, yearFrom, yearTo, ventureId);
        }
        List<ReportAverageScoreDto> listData = new ArrayList<>();
        for (Object[] obj : listObject) {
            ReportAverageScoreDto reportAverageScoreDto = new ReportAverageScoreDto();
            reportAverageScoreDto.setAgentName(obj[0].toString());
            //reportAverageScoreDto.setWeek(Integer.parseInt(obj[1].toString()));
            reportAverageScoreDto.setPeriodYear(obj[1].toString());
            //reportAverageScoreDto.setYear(Integer.parseInt(obj[2].toString()));
            reportAverageScoreDto.setAvg(Double.parseDouble(obj[2].toString()));
            
            listData.add(reportAverageScoreDto);
        }
        return listData;
    }
    
    public List<ReportAVGScoreMapWeekDto> findDataReportAvgScore(int typePeriod, int periodFrom, int periodTo, Integer chanelId, int group, List<Integer> groupIdValue, int yearFrom, int yearTo, Integer ventureId) {
        List<ReportAverageScoreDto> listData = null;
        if (typePeriod == Constants.PERIOD_TYPE_WEEKLY) {
            listData = parseDataReportAverageScore(Constants.PERIOD_TYPE_WEEKLY, periodFrom, periodTo, chanelId, group, groupIdValue, yearFrom, yearTo, ventureId);
        } else if (typePeriod == Constants.PERIOD_TYPE_MONTHLY){
            listData = parseDataReportAverageScore(Constants.PERIOD_TYPE_MONTHLY, periodFrom, periodTo, chanelId, group, groupIdValue, yearFrom, yearTo, ventureId);
        } else {
            listData = parseDataReportAverageScore(Constants.PERIOD_TYPE_QUARTERLY, periodFrom, periodTo, chanelId, group, groupIdValue, yearFrom, yearTo, ventureId);
        }
        SortedMap<String, ArrayList<Object>> mapByWeek = ApplicationCommon.collectionToHash(listData, "getPeriodYear");
        SortedMap<String, ArrayList<Object>> mapByAgent = ApplicationCommon.collectionToHash(listData, "getAgentName");
        //SortedMap<String, ArrayList<Object>> mapByYear = ApplicationCommon.collectionToHash(listData, "getYear");
        List<ReportAVGScoreMapWeekDto> list = getListReportAVGScoreMapWeekDto(mapByWeek, mapByAgent);
        
        return list;
    }
    
    
    
    private List<ReportAVGScoreMapWeekDto> getListReportAVGScoreMapWeekDto(SortedMap<String, ArrayList<Object>> mapByWeek, SortedMap<String, ArrayList<Object>> mapByAgent) {
        List<ReportAVGScoreMapWeekDto> list = new ArrayList<>();
        for (String agentName : mapByAgent.keySet()) {
            ReportAVGScoreMapWeekDto obj = new ReportAVGScoreMapWeekDto();
            obj.setAgentName(agentName);
           
                for (String week : mapByWeek.keySet()) {
                    double score = 0;
                    ArrayList<Object> listObj = (ArrayList<Object>)mapByWeek.get(week);
                    for (Object objFromWeek : listObj) {
                        ReportAverageScoreDto reportAverageScoreDto = (ReportAverageScoreDto)objFromWeek;

                        if (agentName.equals(reportAverageScoreDto.getAgentName())) {                       
                            score = reportAverageScoreDto.getAvg();                        
                        }

                    }
                    obj.getMapWeekAndScore().put(week, score);
                }
                
            
            list.add(obj);
        }
        return list;
    }
    
    private List<ReportPerOfCateDto> parseDataReportPercentOfCate(int typePeriod, int periodFrom, int periodTo, Integer chanelId, int group, List<Integer> groupIdValues, int yearFrom, int yearTo, Integer ventureId) {
        List<Object[]> listObject = null;
        if (typePeriod == Constants.PERIOD_TYPE_WEEKLY) {
            listObject = new AttributeGroupDao().findPerOfCateReportWeek(periodFrom, periodTo, chanelId, group, groupIdValues, yearFrom, ventureId);
        } else if (typePeriod == Constants.PERIOD_TYPE_MONTHLY){
            listObject = new AttributeGroupDao().findPerOfCateReportMonth(periodFrom, periodTo, chanelId, group, groupIdValues, yearFrom, yearTo, ventureId);
        } else {
            listObject = new AttributeGroupDao().findPerOfCateReportQuarter(periodFrom, periodTo, chanelId, group, groupIdValues, yearFrom, yearTo, ventureId);
        }
        List<ReportPerOfCateDto> listData = new ArrayList<>();
        for (Object[] obj : listObject) {
            ReportPerOfCateDto reportPerOfCateDto = new ReportPerOfCateDto();
            reportPerOfCateDto.setAgentName(obj[0].toString());            
            reportPerOfCateDto.setGroupAttributeName(obj[1] != null ? obj[1].toString() : "");
            reportPerOfCateDto.setValuePercent(Double.parseDouble(obj[2] != null ? obj[2].toString() : "0"));
            
            listData.add(reportPerOfCateDto);
        }
        return listData;
    }
    
    public List<ReportPerOfCateMapDto> findDataReportPerOfCate(int typePeriod, int periodFrom, int periodTo, Integer chanelId, int group, List<Integer> groupIdValue, int yearFrom, int yearTo, Integer ventureId) {
        List<ReportPerOfCateDto> listData = parseDataReportPercentOfCate(typePeriod, periodFrom, periodTo, chanelId, group, groupIdValue, yearFrom, yearTo, ventureId);
       
        SortedMap<String, ArrayList<Object>> mapByGroupAttr = ApplicationCommon.collectionToHash(listData, "getGroupAttributeName");
        SortedMap<String, ArrayList<Object>> mapByAgent = ApplicationCommon.collectionToHash(listData, "getAgentName");
        
        List<ReportPerOfCateMapDto> list = getListReportPerOfCateMapDto(mapByGroupAttr, mapByAgent);
        
        return list;
    }
    
    private List<ReportPerOfCateMapDto> getListReportPerOfCateMapDto(SortedMap<String, ArrayList<Object>> mapByGroupAttr, SortedMap<String, ArrayList<Object>> mapByAgent) {
        List<ReportPerOfCateMapDto> list = new ArrayList<>();
        for (String agentName : mapByAgent.keySet()) {
            ReportPerOfCateMapDto obj = new ReportPerOfCateMapDto();
            obj.setAgentName(agentName);
           
                for (String groupAttrName : mapByGroupAttr.keySet()) {
                    double score = 0;
                    ArrayList<Object> listObj = (ArrayList<Object>)mapByGroupAttr.get(groupAttrName);
                    for (Object objFromGroup : listObj) {
                        ReportPerOfCateDto reportPerOfCateDto = (ReportPerOfCateDto)objFromGroup;

                        if (agentName.equals(reportPerOfCateDto.getAgentName())) {                       
                            score = reportPerOfCateDto.getValuePercent();                        
                        }

                    }
                    obj.getMapGaroupAttrValue().put(groupAttrName, score);
                }
                
            
            list.add(obj);
        }
        return list;
    }
    
    
    private List<ReportPerOfAttrDto> parseDataReportPercentOfAttr(int typePeriod, int periodFrom, int periodTo, Integer chanelId, int group, List<Integer> groupIdValues, int yearFrom, int yearTo, Integer ventureId) {
        List<Object[]> listObject = null;
        if (typePeriod == Constants.PERIOD_TYPE_WEEKLY) {
            listObject = new AttributeDao().findPerOfAttrReportWeek(periodFrom, periodTo, chanelId, group, groupIdValues, yearFrom, ventureId);
        } else if (typePeriod == Constants.PERIOD_TYPE_MONTHLY){
            listObject = new AttributeDao().findPerOfAttrReportMonth(periodFrom, periodTo, chanelId, group, groupIdValues, yearFrom, yearTo, ventureId);
        } else {
            listObject = new AttributeDao().findPerOfAttrReportQuarter(periodFrom, periodTo, chanelId, group, groupIdValues, yearFrom, yearTo, ventureId);
        }
        List<ReportPerOfAttrDto> listData = new ArrayList<>();
        for (Object[] obj : listObject) {
            ReportPerOfAttrDto reportPerOfAttrDto = new ReportPerOfAttrDto();
            reportPerOfAttrDto.setAgentName(obj[0].toString());            
            reportPerOfAttrDto.setGroupAttributeName(obj[1].toString());            
            reportPerOfAttrDto.setAttributeName(obj[2].toString());
            reportPerOfAttrDto.setValuePercent(Double.parseDouble(obj[3] != null ? obj[3].toString() : "0"));
            
            listData.add(reportPerOfAttrDto);
        }
        return listData;
    }
    
    public List<ReportPerOfAttrMapDto> findDataReportPerOfAttr(int typePeriod, int periodFrom, int periodTo, Integer chanelId, int group, List<Integer> groupIdValue, int yearFrom, int yearTo, Integer ventureId) {
        List<ReportPerOfAttrDto> listData = parseDataReportPercentOfAttr(typePeriod, periodFrom, periodTo, chanelId, group, groupIdValue, yearFrom, yearTo, ventureId);
       
        SortedMap<String, ArrayList<Object>> mapByAttr = ApplicationCommon.collectionToHash(listData, "getAttributeName");
        SortedMap<String, ArrayList<Object>> mapByAgent = ApplicationCommon.collectionToHash(listData, "getAgentName");
        
        List<ReportPerOfAttrMapDto> list = getListReportPerOfAttrMapDto(mapByAttr, mapByAgent);
        
        return list;
    }
    
    private List<ReportPerOfAttrMapDto> getListReportPerOfAttrMapDto(SortedMap<String, ArrayList<Object>> mapByAttr, SortedMap<String, ArrayList<Object>> mapByAgent) {
        List<ReportPerOfAttrMapDto> list = new ArrayList<>();
        for (String agentName : mapByAgent.keySet()) {
            ReportPerOfAttrMapDto obj = new ReportPerOfAttrMapDto();
            obj.setAgentName(agentName);
           
                for (String attrName : mapByAttr.keySet()) {
                    double score = 0;
                    ArrayList<Object> listObj = (ArrayList<Object>)mapByAttr.get(attrName);
                    for (Object objFromGroup : listObj) {
                        ReportPerOfAttrDto reportPerOfAttrDto = (ReportPerOfAttrDto)objFromGroup;

                        if (agentName.equals(reportPerOfAttrDto.getAgentName())) {                       
                            score = reportPerOfAttrDto.getValuePercent();                        
                        }

                    }
                    obj.getMapAttrValue().put(attrName, score);
                }
                
            
            list.add(obj);
        }
        return list;
    }
    
    public List<ReportTotalEvaluationDto> parseDataReportTotalEvaluation(int typePeriod, int periodFrom, int periodTo, Integer chanelId, int group, List<Integer> groupIdValues, int yearFrom, int yearTo, Integer ventureId) {
        List<Object[]> listObject = null;
        if (typePeriod == Constants.PERIOD_TYPE_WEEKLY) {
            listObject = new ScorecardDao().findTotalEvaluationReportWeek(periodFrom, periodTo, chanelId, group, groupIdValues, yearFrom, ventureId);
        } else if (typePeriod == Constants.PERIOD_TYPE_MONTHLY){
            listObject = new ScorecardDao().findTotalEvaluationReportMonth(periodFrom, periodTo, chanelId, group, groupIdValues, yearFrom, yearTo, ventureId);
        } else {
            listObject = new ScorecardDao().findTotalEvaluationReportQuarter(periodFrom, periodTo, chanelId, group, groupIdValues, yearFrom, yearTo, ventureId);
        }
        List<ReportTotalEvaluationDto> listData = new ArrayList<>();
        for (Object[] obj : listObject) {
            ReportTotalEvaluationDto reportTotalEvaluationDto = new ReportTotalEvaluationDto();
            reportTotalEvaluationDto.setAgentName(obj[0].toString());
            //reportAverageScoreDto.setWeek(Integer.parseInt(obj[1].toString()));
            reportTotalEvaluationDto.setPeriodYear(obj[1].toString());
            //reportAverageScoreDto.setYear(Integer.parseInt(obj[2].toString()));
            reportTotalEvaluationDto.setAvg(Double.parseDouble(obj[2].toString()));
            
            listData.add(reportTotalEvaluationDto);
        }
        return listData;
    }
    
    public List<ReportTotalEvaluationMapWeekDto> findDataReportTotalEvaluation(int typePeriod, int periodFrom, int periodTo, Integer chanelId, int group, List<Integer> groupIdValue, int yearFrom, int yearTo, Integer ventureId) {
        List<ReportTotalEvaluationDto> listData = null;
        if (typePeriod == Constants.PERIOD_TYPE_WEEKLY) {
            listData = parseDataReportTotalEvaluation(Constants.PERIOD_TYPE_WEEKLY, periodFrom, periodTo, chanelId, group, groupIdValue, yearFrom, yearTo, ventureId);
        } else if (typePeriod == Constants.PERIOD_TYPE_MONTHLY){
            listData = parseDataReportTotalEvaluation(Constants.PERIOD_TYPE_MONTHLY, periodFrom, periodTo, chanelId, group, groupIdValue, yearFrom, yearTo, ventureId);
        } else {
            listData = parseDataReportTotalEvaluation(Constants.PERIOD_TYPE_QUARTERLY, periodFrom, periodTo, chanelId, group, groupIdValue, yearFrom, yearTo, ventureId);
        }
        SortedMap<String, ArrayList<Object>> mapByWeek = ApplicationCommon.collectionToHash(listData, "getPeriodYear");
        SortedMap<String, ArrayList<Object>> mapByAgent = ApplicationCommon.collectionToHash(listData, "getAgentName");
        //SortedMap<String, ArrayList<Object>> mapByYear = ApplicationCommon.collectionToHash(listData, "getYear");
        List<ReportTotalEvaluationMapWeekDto> list = getListReportTotalEvaluationMapWeekDto(mapByWeek, mapByAgent);
        
        return list;
    }
    
    
    
    private List<ReportTotalEvaluationMapWeekDto> getListReportTotalEvaluationMapWeekDto(SortedMap<String, ArrayList<Object>> mapByWeek, SortedMap<String, ArrayList<Object>> mapByAgent) {
        List<ReportTotalEvaluationMapWeekDto> list = new ArrayList<>();
        for (String agentName : mapByAgent.keySet()) {
            ReportTotalEvaluationMapWeekDto obj = new ReportTotalEvaluationMapWeekDto();
            obj.setAgentName(agentName);
           
                for (String week : mapByWeek.keySet()) {
                    double score = 0;
                    ArrayList<Object> listObj = (ArrayList<Object>)mapByWeek.get(week);
                    for (Object objFromWeek : listObj) {
                        ReportTotalEvaluationDto reportTotalEvaluationDto = (ReportTotalEvaluationDto)objFromWeek;

                        if (agentName.equals(reportTotalEvaluationDto.getAgentName())) {                       
                            score = reportTotalEvaluationDto.getAvg();                        
                        }

                    }
                    obj.getMapWeekAndScore().put(week, score);
                }
                
            
            list.add(obj);
        }
        return list;
    }
}
